package com.wtwd.device.protocol;

import com.wtwd.device.constant.SeparatorConstant;
import com.wtwd.device.util.StringUtils;
import io.netty.buffer.ByteBuf;
import io.netty.util.CharsetUtil;
import lombok.Builder;

import java.io.Serializable;
import java.nio.charset.StandardCharsets;

@Builder
public class WTProtocol implements Serializable {

    private static final long serialVersionUID = 3994827891344L;

    /**
     * 起始位标记符
     */
    private static String startBit = "[";

    /**
     * 结束位标记符
     */
    private static String endBit = "]";

    /**
     * 分隔符
     */
    private static String separator = ",";

    /**
     * 设备唯一编号  长度不定
     */
    private String imei;

    /**
     * SIM卡卡号
     */
    private String iccid;

    /**
     * 交易流水号
     * 时间格式+4位循环数，时间格式: yyyyMMddHHmmss
     * 4位循环数范围0..9999，从0开始，递增赋值，步长为1，增加到9999后，再从0开始
     */
    private String number;

    /**
     * 指令名称
     */
    private String cmdName;

    /**
     * 报文类型
     */
    private String mesType;

    /**
     * 设备时间
     */
    private String time;

    /**
     * 报文内容长度
     */
    private Integer bodyLength;

    /**
     * 消息体报文
     */
    private String body;


    public static String getStartBit() {
        return startBit;
    }

    public static void setStartBit(String startBit) {
        WTProtocol.startBit = startBit;
    }

    public static String getEndBit() {
        return endBit;
    }

    public static void setEndBit(String endBit) {
        WTProtocol.endBit = endBit;
    }

    public static String getSeparator() {
        return separator;
    }

    public static void setSeparator(String separator) {
        WTProtocol.separator = separator;
    }

    public String getImei() {
        return imei;
    }

    public void setImei(String imei) {
        this.imei = imei;
    }

    public String getIccid() {
        return iccid;
    }

    public void setIccid(String iccid) {
        this.iccid = iccid;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public String getCmdName() {
        return cmdName;
    }

    public void setCmdName(String cmdName) {
        this.cmdName = cmdName;
    }

    public String getMesType() {
        return mesType;
    }

    public void setMesType(String mesType) {
        this.mesType = mesType;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }

    public Integer getBodyLength() {
        return bodyLength;
    }

    public void setBodyLength(Integer bodyLength) {
        this.bodyLength = bodyLength;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }


    public WTProtocol initProtocol(ByteBuf dataBuf) {
        // 获取可读字节数
        int idx = dataBuf.readerIndex();
        //创建与ByteBuf中可读字节数相同的数组
        byte[] bytes = new byte[dataBuf.readableBytes()];
        //计算读取时这一包的结束位置
        int totalstr = idx + bytes.length;
        while (idx != totalstr) {
            bytes[idx - dataBuf.readerIndex()] = dataBuf.getByte(idx++);
        }
        String datastr = new String(bytes, CharsetUtil.UTF_8);
        int index = datastr.indexOf(startBit);//标记头首次出现的位置
        if (index < 0) {//没有该头部标记则全部丢弃掉
            dataBuf.skipBytes(datastr.length());
            datastr = "";
        } else if (index > 0) {
            dataBuf.skipBytes(index);
            datastr = datastr.substring(index, datastr.length());
        }
        //分隔符第7次出现的位置则为消息头,取消息头并用逗号进行分割 dataStr[0] 为字符串头 data[1]为字符串后面的部分
        String[] dataStrArray = splitAtNthOccurrence(datastr, SeparatorConstant.COMMA,7);
        if (StringUtils.isEmpty(dataStrArray[0]) || StringUtils.isEmpty(dataStrArray[1])) {//消息头或者消息尾任意为空则断包
            return null;
        }
        String headerStr = dataStrArray[0];
        String[] split = headerStr.split(separator);
        if (split.length < 7) return null;//断包
        String imei = split[0].substring(1);//去掉头部标记剩下的为imei
        String iccid = split[1];
        String number = split[2];
        String cmdName = split[3];
        String mesType = split[4];
        String time = split[5];
        Integer bodyLength = Integer.valueOf(split[6]);
        if (bodyLength + endBit.length() > dataStrArray[1].length()) {
            return null;//消息体内容长度加结束标记符大于尾部长度断包
        }
        int headerLength = startBit.length() + imei.length() + separator.length() + iccid.length() + separator.length() + number.length() + separator.length()
                + cmdName.length() + separator.length() + mesType.length() + separator.length() + time.length() + separator.length()
                + bodyLength.toString().length() + separator.length();
        //如果消息尾部第一次出现结束标记符号不在
        String body = dataStrArray[1].substring(0, bodyLength);
        Integer total = headerLength + bodyLength + endBit.length();
        if (!endBit.equals(Character.toString(dataStrArray[1].charAt(bodyLength)))) {//该位置不是结束标记则认为该消息为错误协议丢弃
            dataBuf.skipBytes(total);
            return this;
        }
        dataBuf.skipBytes(total);
        //将读指针移动到读取数据的末尾
        return WTProtocol.builder().imei(imei).iccid(iccid).number(number).cmdName(cmdName)
                .mesType(mesType).time(time).bodyLength(bodyLength).body(body).build();
    }

    public String serialize() {
        String msgHandler = startBit.concat(imei).concat(separator).concat(iccid).concat(separator)
                .concat(number).concat(separator).concat(cmdName).concat(separator).concat(mesType).concat(separator)
                .concat(time).concat(separator).concat(String.valueOf(bodyLength)).concat(separator);
        byte[] startBit = {0x0D,0x0A,0x00};
        return msgHandler.concat(body).concat(endBit).concat(new String(startBit, StandardCharsets.UTF_8));
    }


    /**
     * * 返回0号位标识 分割符前面的部分
     * * 1号位标识 分割符后面的部分
     *
     * @param input
     * @param delimiter
     * @param n
     * @return
     */
    public static String[] splitAtNthOccurrence(String input, String delimiter, int n) {
        int index = -1;
        int fromIndex = 0;

        for (int i = 0; i < n; i++) {
            index = input.indexOf(delimiter, fromIndex);
            if (index == -1) {
                return null; // delimiter does not occur n times
            }
            fromIndex = index + delimiter.length();
        }

        String before = input.substring(0, index);
        String after = input.substring(index + delimiter.length());

        return new String[]{before, after};
    }

    public static void main(String[] args) {
        String str="[35380100360180,898600MFSSYYGXXXXX80,202004211045001000,DEVICE_LOGIN,3,465456456,41,5@1@1@0@1@21@device_version@model_version]";
        String[] strings = splitAtNthOccurrence(str, ",", 7);
        System.out.println(strings[0]+"|||"+strings[1]);
    }
    @Override
    public String toString() {
        return "WTProtocol{" +
                "imei='" + imei + '\'' +
                ", iccid='" + iccid + '\'' +
                ", number='" + number + '\'' +
                ", cmdName='" + cmdName + '\'' +
                ", mesType='" + mesType + '\'' +
                ", time='" + time + '\'' +
                ", bodyLength=" + bodyLength +
                ", body='" + body + '\'' +
                '}';
    }

}
